package org.ycx.generator.code;

import org.apache.velocity.VelocityContext;
import org.ycx.common.annotation.FormDesc;
import org.ycx.common.util.VelocityUtil;
import org.ycx.generator.GenNode;

import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import static org.ycx.common.util.StringUtil.humpToPackage;


/**
 * 页面生成类
 */
public class PageCodeGeneratorUtil {

    public static String indexPage_vm = "/templates/vm/index.vm";
    public static String indexJS_vm = "/templates/vm/indexJS.vm";
    public static String createPage_vm = "/templates/vm/create.vm";
    public static String updatePage_vm = "/templates/vm/update.vm";
    public static String detailPage_vm = "/templates/vm/detail.vm";

    public static Set<String> ignoreFields = new HashSet<String>();

    private static void init() {
        ignoreFields.add("createTs");
        ignoreFields.add("updateTs");
        ignoreFields.add("createUid");
        ignoreFields.add("updateUid");
        ignoreFields.add("delState");
    }

    public static void generator(
            String module,
            String path,
            Set<String> models, boolean overrride) throws Exception {

        String project = System.getProperty("user.dir") + File.separator + module;
        indexPage_vm = project + "/src/main/resources" + indexPage_vm;
        indexJS_vm = project + "/src/main/resources" + indexJS_vm;
        createPage_vm = project + "/src/main/resources" + createPage_vm;
        updatePage_vm = project + "/src/main/resources" + updatePage_vm;
        detailPage_vm = project + "/src/main/resources" + detailPage_vm;
        String pagePath = project + "/src/main/resources/templates/" + path.replaceAll("\\.", "/") + "/";
        String jsPath = project + "/src/main/resources/static/js/" + path.replaceAll("\\.", "/") + "/";

        init();
        for (String modelName : models) {
            Class model = Class.forName(modelName);
            String pk = ((FormDesc) model.getAnnotation(FormDesc.class)).pk();
            boolean midTable = ((FormDesc) model.getAnnotation(FormDesc.class)).isMidTable();
            if (midTable) {
                continue;
            }
            String modelSimpelName = model.getSimpleName();
            String PageoutPath = pagePath + "/" + humpToPackage(modelSimpelName);
            String jsOutPath = jsPath + "/" + humpToPackage(modelSimpelName);
            if (!new File(PageoutPath).exists()) {
                new File(PageoutPath).mkdirs();
            }
            if (!new File(jsOutPath).exists()) {
                new File(jsOutPath).mkdirs();
            }
            //首页
            VelocityContext context = new VelocityContext();
            context.put("model", modelSimpelName);
            context.put("nodes", modelsGen(model));
            context.put("pk", pk);
            context.put("impJS", "/js/" + path + humpToPackage(modelSimpelName) + "/index.js");
            if (overrride) {
                VelocityUtil.generate(indexPage_vm, PageoutPath + "/index.html", context);
            } else {
                if (!new File(PageoutPath + "/index.html").exists()) {
                    VelocityUtil.generate(indexPage_vm, PageoutPath + "/index.html", context);
                }
            }

            VelocityContext jsContext = new VelocityContext();
            jsContext.put("model", modelSimpelName);
            jsContext.put("nodes", modelsGen(model));
            jsContext.put("pk", pk);
            jsContext.put("ROOT_URI", humpToPackage(modelSimpelName));
            if (overrride) {
                VelocityUtil.generate(indexJS_vm, jsOutPath + "/index.js", jsContext);
            } else {
                if (!new File(jsOutPath + "/index.js").exists()) {
                    VelocityUtil.generate(indexJS_vm, jsOutPath + "/index.js", jsContext);
                }
            }


            //创建页面
            VelocityContext createcontext = new VelocityContext();
            createcontext.put("nodes", modelsGen(model));
            createcontext.put("pk", pk);
            createcontext.put("model", modelSimpelName);
            createcontext.put("impJS", "/js/" + path + humpToPackage(modelSimpelName) + "/create.js");
            if (overrride) {
                VelocityUtil.generate(createPage_vm, PageoutPath + "/create.html", createcontext);
            } else {
                if (!new File(PageoutPath + "/create.html").exists()) {
                    VelocityUtil.generate(createPage_vm, PageoutPath + "/create.html", createcontext);
                }
            }

            //更新页面
            VelocityContext updatecontext = new VelocityContext();
            updatecontext.put("nodes", modelsGen(model));
            updatecontext.put("pk", pk);
            updatecontext.put("model", modelSimpelName);
            updatecontext.put("ROOT_URI", humpToPackage(modelSimpelName));
            updatecontext.put("impJS", "/js/" + path + humpToPackage(modelSimpelName) + "/update.js");
            if (overrride) {
                VelocityUtil.generate(updatePage_vm, PageoutPath + "/update.html", updatecontext);
            } else {
                if (!new File(PageoutPath + "/update.html").exists()) {
                    VelocityUtil.generate(updatePage_vm, PageoutPath + "/update.html", updatecontext);
                }
            }
            //详情页面
            VelocityContext detailContext = new VelocityContext();
            detailContext.put("nodes", modelsGen(model));
            detailContext.put("pk", pk);
            detailContext.put("impJS", "/js/" + path + humpToPackage(modelSimpelName) + "/detail.js");

            if (overrride) {
                VelocityUtil.generate(detailPage_vm, PageoutPath + "/detail.html", detailContext);
            } else {
                if (!new File(PageoutPath + "/detail.html").exists()) {
                    VelocityUtil.generate(detailPage_vm, PageoutPath + "/detail.html", detailContext);
                }
            }
        }

    }

    private static List<GenNode> modelsGen(Class clazz) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Field[] fields = clazz.getDeclaredFields();
        List<GenNode> nodes = new ArrayList<GenNode>();
        //获取自动model的字段
        for (int i = 0; i < fields.length; ++i) {
            if (!ignoreFields.contains(fields[i].getName()) && !Modifier.isStatic(fields[i].getModifiers())) {
                FormDesc desc = fields[i].getAnnotation(FormDesc.class);
                GenNode node = new GenNode(desc.name(), fields[i].getName(), desc.maxLength());
                node.setType(desc.type());
                if (desc.type() == 4) {
                    //选择框
                    Method method = desc.choice().getMethod("values");
                    node.setChoices((Object[]) method.invoke(desc.choice()));
                }
                node.setPrecision(desc.precision());
                nodes.add(node);
            }
        }
        return nodes;
    }


    // 递归删除非空文件夹
    public static void deleteDir(File dir) {
        if (dir.isDirectory()) {
            File[] files = dir.listFiles();
            for (int i = 0; i < files.length; i++) {
                deleteDir(files[i]);
            }
        }
        dir.delete();
    }
}
